/**
 * @file    DAP_config.h
 * @brief
 *
 * DAPLink Interface Firmware
 * Copyright (c) 2009-2021, ARM Limited, All Rights Reserved
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef __DAP_CONFIG_H__
#define __DAP_CONFIG_H__

#include "IO_Config.h"
#include "swd_host.h"
#include "stm32f103xb.h"

/*提供有关调试单元的硬件及配置的定义。
该信息包含以下内容：
CMSIS-DAP 调试单元中所使用的 Cortex-M 处理器参数的定义。
调试单元标识字符串（供应商、产品、序列号）。
调试单元通信数据包大小。
调试访问端口支持的模式及设置（JTAG / 串行线调试（SWD）以及串行线查看器（SWO））。
有关所连接目标设备（针对评估板）的可选信息。
调试单元中所使用的 Cortex-M 微控制器的处理器时钟。
该数值用于计算串行线调试（SWD）/ JTAG 时钟速度。*/
#define CPU_CLOCK SystemCoreClock ///< Specifies the CPU Clock in Hz

/*I/O 端口写操作的处理器周期数。
该数值用于计算由 Cortex-M 微控制器在调试单元中通过 I/O 端口写操作所产生的串行线调试（SWD）/JTAG 时钟速度。
大多数 Cortex-M 处理器进行一次 I/O 端口写操作需要 2 个处理器周期。如果调试单元使用的是仅具备高速外设 I/O 
的 Cortex-M0 + 处理器，那么可能仅需 1 个处理器周期。*/
#define IO_PORT_WRITE_CYCLES 2U ///< I/O Cycles: 2=default, 1=Cortex-M0+ fast I/0

/*表明串行线调试（SWD）通信模式在调试访问端口可用。*/
#define DAP_SWD 1 ///< SWD Mode:  1 = available, 0 = not available

/* 表明 JTAG 通信模式在调试端口可用。
 此信息由 DAP_Info 命令作为功能特性的一部分返回*/
#define DAP_JTAG 0 ///< JTAG Mode: 1 = available, 0 = not available.

/*配置连接到调试访问端口的扫描链上 JTAG 设备的最大数量。
该设置会影响调试单元的随机存取存储器（RAM）需求。有效范围是 1 到 255。 */
#define DAP_JTAG_DEV_CNT (ENABLE_JTAG ? 8 : 0) ///< Maximum number of JTAG devices on scan chain

/*调试访问端口上的默认通信模式。
当选择端口默认模式时，用于 DAP_Connect 命令。*/
#define DAP_DEFAULT_PORT 1 ///< Default JTAG/SWJ Port Mode: 1 = SWD, 2 = JTAG.

/*调试访问端口上串行线调试（SWD）和 JTAG 模式的默认通信速度。
用于初始化默认的 SWD/JTAG 时钟频率。
可以使用 DAP_SWJ_Clock 命令来覆盖此默认设置。*/
#define DAP_DEFAULT_SWJ_CLOCK 10000000 ///< Default SWD/JTAG clock frequency in Hz.

/*命令及响应数据的最大数据包大小。
此配置设置用于优化与调试器的通信性能，并且取决于 USB 外设。典型数值为：对于全速 USB 人机接
口设备（HID）或 WinUSB 而言是 64；对于高速 USB 人机接口设备（HID）是 1024；对于高速 USB WinUSB 是 512。*/
#ifndef HID_ENDPOINT        // HID end points currently set limits to 64
#define DAP_PACKET_SIZE 512 ///< Specifies Packet Size in bytes.
#else
#define DAP_PACKET_SIZE 64 ///< Specifies Packet Size in bytes.
#endif

/*命令及响应数据的最大数据包缓冲区数量。
此配置设置用于优化与调试器的通信性能，并且取决于 USB 外设。对于随机存取存储器（RAM）
或 USB 缓冲区有限的设备，可减小该设置值（有效范围是 1 到 255）。对于高速 USB，可将设置更改为 4。*/
#define DAP_PACKET_COUNT 64 ///< Buffers: 64 = Full-Speed, 4 = High-Speed.

/*表明通用异步收发传输器（UART）串行线输出（SWO）跟踪功能可用。
此信息由  DAP_Info 命令作为功能特性的一部分返回。*/
#define SWO_UART 0 ///< SWO UART:  1 = available, 0 = not available

/*USART Driver instance number for the UART SWO.*/
#define SWO_UART_DRIVER 0 ///< USART Driver instance number (Driver_USART#).

/// Maximum SWO UART Baudrate
#define SWO_UART_MAX_BAUDRATE 10000000U ///< SWO UART Maximum Baudrate in Hz

/// Indicate that Manchester Serial Wire Output (SWO) trace is available.
/// This information is returned by the command \ref DAP_Info as part of <b>Capabilities</b>.
#define SWO_MANCHESTER 0 ///< SWO Manchester:  1 = available, 0 = not available.

/// SWO Trace Buffer Size.
#define SWO_BUFFER_SIZE 8192U ///< SWO Trace Buffer Size in bytes (must be 2^n).

/// SWO Streaming Trace.
#define SWO_STREAM 0 ///< SWO Streaming Trace: 1 = available, 0 = not available.

/// Clock frequency of the Test Domain Timer. Timer value is returned with \ref TIMESTAMP_GET.
#define TIMESTAMP_CLOCK 1000000U ///< Timestamp clock in Hz (0 = timestamps not supported).

/// Indicate that UART Communication Port is available.
/// This information is returned by the command \ref DAP_Info as part of <b>Capabilities</b>.
#define DAP_UART 0 ///< DAP UART:  1 = available, 0 = not available.

/// USART Driver instance number for the UART Communication Port.
#define DAP_UART_DRIVER 1 ///< USART Driver instance number (Driver_USART#).

/// UART Receive Buffer Size.
#define DAP_UART_RX_BUFFER_SIZE 2048U ///< Uart Receive Buffer Size in bytes (must be 2^n).

/// UART Transmit Buffer Size.
#define DAP_UART_TX_BUFFER_SIZE 2048U ///< Uart Transmit Buffer Size in bytes (must be 2^n).

/// Indicate that UART Communication via USB COM Port is available.
/// This information is returned by the command \ref DAP_Info as part of <b>Capabilities</b>.
#define DAP_UART_USB_COM_PORT 1 ///< USB COM Port:  1 = available, 0 = not available.

/// Debug Unit is connected to fixed Target Device.
/// The Debug Unit may be part of an evaluation board and always connected to a fixed
/// known device. In this case a Device Vendor, Device Name, Board Vendor and Board Name strings
/// are stored and may be used by the debugger or IDE to configure device parameters.
#define TARGET_FIXED 0 ///< Target: 1 = known, 0 = unknown;

///@}

__STATIC_INLINE void pin_out_init(GPIO_TypeDef *GPIOx, uint8_t pin_bit)
{
    if (pin_bit >= 8)
    {
        GPIOx->CRH &= ~(0x0000000F << ((pin_bit - 8) << 2));
        GPIOx->CRH |= (((uint32_t)(0x00 | 0x03) & 0x0F) << ((pin_bit - 8) << 2));
    }
    else
    {
        GPIOx->CRL &= ~(0x0000000F << ((pin_bit) << 2));
        GPIOx->CRL |= (((uint32_t)(0x00 | 0x03) & 0x0F) << ((pin_bit) << 2));
    }
}

__STATIC_INLINE void pin_out_od_init(GPIO_TypeDef *GPIOx, uint8_t pin_bit)
{
    if (pin_bit >= 8)
    {
        GPIOx->CRH &= ~(0x0000000F << ((pin_bit - 8) << 2));
        GPIOx->CRH |= (((uint32_t)(0x04 | 0x03) & 0x0F) << ((pin_bit - 8) << 2));
    }
    else
    {
        GPIOx->CRL &= ~(0x0000000F << ((pin_bit) << 2));
        GPIOx->CRL |= (((uint32_t)(0x04 | 0x03) & 0x0F) << ((pin_bit) << 2));
    }
}

__STATIC_INLINE void pin_in_init(GPIO_TypeDef *GPIOx, uint8_t pin_bit, uint8_t mode)
{
    uint8_t config;
    if (mode == 1)
        config = 0x08; // Up
    else if (mode == 2)
        config = 0x08; // down
    else
        config = 0x00; // GPIO_Mode_AIN

    if (pin_bit >= 8)
    {
        GPIOx->CRH &= ~(0x0000000F << ((pin_bit - 8) << 2));
        GPIOx->CRH |= (((uint32_t)(config) & 0x0F) << ((pin_bit - 8) << 2));
        if (mode == 1)
            GPIOx->BSRR = (((uint32_t)0x01) << pin_bit);
        else if (mode == 2)
            GPIOx->BRR = (((uint32_t)0x01) << pin_bit);
    }
    else
    {
        GPIOx->CRL &= ~(0x0000000F << ((pin_bit) << 2));
        GPIOx->CRL |= (((uint32_t)(config) & 0x0F) << ((pin_bit) << 2));
        if (mode == 1)
            GPIOx->BSRR = (((uint32_t)0x01) << pin_bit);
        else if (mode == 2)
            GPIOx->BRR = (((uint32_t)0x01) << pin_bit);
    }
}
//**************************************************************************************************
/**
\defgroup DAP_Config_PortIO_gr CMSIS-DAP Hardware I/O Pin Access
\ingroup DAP_ConfigIO_gr
@{

Standard I/O Pins of the CMSIS-DAP Hardware Debug Port support standard JTAG mode
and Serial Wire Debug (SWD) mode. In SWD mode only 2 pins are required to implement the debug
interface of a device. The following I/O Pins are provided:

JTAG I/O Pin                 | SWD I/O Pin          | CMSIS-DAP Hardware pin mode
---------------------------- | -------------------- | ---------------------------------------------
TCK: Test Clock              | SWCLK: Clock         | Output Push/Pull
TMS: Test Mode Select        | SWDIO: Data I/O      | Output Push/Pull; Input (for receiving data)
TDI: Test Data Input         |                      | Output Push/Pull
TDO: Test Data Output        |                      | Input
nTRST: Test Reset (optional) |                      | Output Open Drain with pull-up resistor
nRESET: Device Reset         | nRESET: Device Reset | Output Open Drain with pull-up resistor


DAP Hardware I/O Pin Access Functions
-------------------------------------
The various I/O Pins are accessed by functions that implement the Read, Write, Set, or Clear to
these I/O Pins.

For the SWDIO I/O Pin there are additional functions that are called in SWD I/O mode only.
This functions are provided to achieve faster I/O that is possible with some advanced GPIO
peripherals that can independently write/read a single I/O pin without affecting any other pins
of the same I/O port. The following SWDIO I/O Pin functions are provided:
 - \ref PIN_SWDIO_OUT_ENABLE to enable the output mode from the DAP hardware.
 - \ref PIN_SWDIO_OUT_DISABLE to enable the input mode to the DAP hardware.
 - \ref PIN_SWDIO_IN to read from the SWDIO I/O pin with utmost possible speed.
 - \ref PIN_SWDIO_OUT to write to the SWDIO I/O pin with utmost possible speed.
*/

// Configure DAP I/O pins ------------------------------

/** Setup JTAG I/O pins: TCK, TMS, TDI, TDO, nTRST, and nRESET.
Configures the DAP Hardware I/O pins for JTAG mode:
 - TCK, TMS, TDI, nTRST, nRESET to output mode and set to high level.
 - TDO to input mode.
*/
__STATIC_INLINE void PORT_JTAG_SETUP(void)
{
#if (DAP_JTAG != 0)
    // TCK output
    pin_out_init(JTAG_TCK_PIN_PORT, JTAG_TCK_PIN_Bit);
    JTAG_TCK_PIN_PORT->BSRR = JTAG_TCK_PIN;

    // TMS output
    pin_out_init(JTAG_TMS_PIN_PORT, JTAG_TMS_PIN_Bit);
    JTAG_TMS_PIN_PORT->BSRR = JTAG_TMS_PIN;
    pin_in_init(SWDIO_IN_PIN_PORT, SWDIO_IN_PIN_Bit, 1);

    // TDI output
    pin_out_init(JTAG_TDI_PIN_PORT, JTAG_TDI_PIN_Bit);
    JTAG_TDI_PIN_PORT->BSRR = JTAG_TDI_PIN;

    // TDO input
    pin_in_init(JTAG_TDO_PIN_PORT, JTAG_TDO_PIN_Bit, 1);

    // Set RESET HIGH
    pin_out_od_init(nRESET_PIN_PORT, nRESET_PIN_Bit); // TODO - fix reset logic
    nRESET_PIN_PORT->BSRR = nRESET_PIN;
#endif
}

/** Setup SWD I/O pins: SWCLK, SWDIO, and nRESET.
Configures the DAP Hardware I/O pins for Serial Wire Debug (SWD) mode:
 - SWCLK, SWDIO, nRESET to output mode and set to default high level.
 - TDI, TMS, nTRST to HighZ mode (pins are unused in SWD mode).
*/
__STATIC_INLINE void PORT_SWD_SETUP(void)
{
    // Set SWCLK HIGH
    pin_out_init(SWCLK_TCK_PIN_PORT, SWCLK_TCK_PIN_Bit);
    SWCLK_TCK_PIN_PORT->BSRR = SWCLK_TCK_PIN;
    // Set SWDIO HIGH
    pin_out_init(SWDIO_OUT_PIN_PORT, SWDIO_OUT_PIN_Bit);
    SWDIO_OUT_PIN_PORT->BSRR = SWDIO_OUT_PIN;

    pin_in_init(SWDIO_IN_PIN_PORT, SWDIO_IN_PIN_Bit, 1);
    // Set RESET HIGH
    pin_out_od_init(nRESET_PIN_PORT, nRESET_PIN_Bit); // TODO - fix reset logic
    nRESET_PIN_PORT->BSRR = nRESET_PIN;
}

/** Disable JTAG/SWD I/O Pins.
Disables the DAP Hardware I/O pins which configures:
 - TCK/SWCLK, TMS/SWDIO, TDI, TDO, nTRST, nRESET to High-Z mode.
*/
__STATIC_INLINE void PORT_OFF(void)
{
    pin_in_init(SWCLK_TCK_PIN_PORT, SWCLK_TCK_PIN_Bit, 0);
    pin_in_init(SWDIO_OUT_PIN_PORT, SWDIO_OUT_PIN_Bit, 0);
    pin_in_init(SWDIO_IN_PIN_PORT, SWDIO_IN_PIN_Bit, 0);
}

// SWCLK/TCK I/O pin -------------------------------------

/** SWCLK/TCK I/O pin: Get Input.
\return Current status of the SWCLK/TCK DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_SWCLK_TCK_IN(void)
{
    return ((SWCLK_TCK_PIN_PORT->ODR & SWCLK_TCK_PIN) ? 1 : 0);
}

/** SWCLK/TCK I/O pin: Set Output to High.
Set the SWCLK/TCK DAP hardware I/O pin to high level.
*/
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_SET(void)
{
    SWCLK_TCK_PIN_PORT->BSRR = SWCLK_TCK_PIN;
}

/** SWCLK/TCK I/O pin: Set Output to Low.
Set the SWCLK/TCK DAP hardware I/O pin to low level.
*/
__STATIC_FORCEINLINE void PIN_SWCLK_TCK_CLR(void)
{
    SWCLK_TCK_PIN_PORT->BRR = SWCLK_TCK_PIN;
}

// SWDIO/TMS Pin I/O --------------------------------------

/** SWDIO/TMS I/O pin: Get Input.
\return Current status of the SWDIO/TMS DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_TMS_IN(void)
{
    return ((SWDIO_IN_PIN_PORT->IDR & SWDIO_IN_PIN) ? 1 : 0);
}

/** SWDIO/TMS I/O pin: Set Output to High.
Set the SWDIO/TMS DAP hardware I/O pin to high level.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_SET(void)
{
    SWDIO_OUT_PIN_PORT->BSRR = SWDIO_OUT_PIN;
}

/** SWDIO/TMS I/O pin: Set Output to Low.
Set the SWDIO/TMS DAP hardware I/O pin to low level.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_TMS_CLR(void)
{
    SWDIO_OUT_PIN_PORT->BRR = SWDIO_OUT_PIN;
}

/** SWDIO I/O pin: Get Input (used in SWD mode only).
\return Current status of the SWDIO DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_SWDIO_IN(void)
{
    return ((SWDIO_IN_PIN_PORT->IDR & SWDIO_IN_PIN) ? 1 : 0);
}

/** SWDIO I/O pin: Set Output (used in SWD mode only).
\param bit Output value for the SWDIO DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT(uint32_t bit)
{
    if (bit & 1)
        SWDIO_OUT_PIN_PORT->BSRR = SWDIO_OUT_PIN;
    else
        SWDIO_OUT_PIN_PORT->BRR = SWDIO_OUT_PIN;
}

/** SWDIO I/O pin: Switch to Output mode (used in SWD mode only).
Configure the SWDIO DAP hardware I/O pin to output mode. This function is
called prior \ref PIN_SWDIO_OUT function calls.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_ENABLE(void)
{
    pin_out_init(SWDIO_OUT_PIN_PORT, SWDIO_OUT_PIN_Bit);
    SWDIO_OUT_PIN_PORT->BRR = SWDIO_OUT_PIN;
}

/** SWDIO I/O pin: Switch to Input mode (used in SWD mode only).
Configure the SWDIO DAP hardware I/O pin to input mode. This function is
called prior \ref PIN_SWDIO_IN function calls.
*/
__STATIC_FORCEINLINE void PIN_SWDIO_OUT_DISABLE(void)
{
    pin_in_init(SWDIO_OUT_PIN_PORT, SWDIO_OUT_PIN_Bit, 0);
    SWDIO_OUT_PIN_PORT->BSRR = SWDIO_OUT_PIN;
}

// TDI Pin I/O ---------------------------------------------

/** TDI I/O pin: Get Input.
\return Current status of the TDI DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_TDI_IN(void)
{
#if (DAP_JTAG != 0)
    return ((JTAG_TDI_PIN_PORT->IDR & JTAG_TDI_PIN) ? 1 : 0);
#else
    return (0); // Not available
#endif
}

/** TDI I/O pin: Set Output.
\param bit Output value for the TDI DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE void PIN_TDI_OUT(uint32_t bit)
{
#if (DAP_JTAG != 0)
    if (bit & 1)
        JTAG_TDI_PIN_PORT->BSRR = JTAG_TDI_PIN;
    else
        JTAG_TDI_PIN_PORT->BRR = JTAG_TDI_PIN;
#else
    ; // Not available
#endif
}

// TDO Pin I/O ---------------------------------------------

/** TDO I/O pin: Get Input.
\return Current status of the TDO DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_TDO_IN(void)
{
#if (DAP_JTAG != 0)
    return ((JTAG_TDO_PIN_PORT->IDR & JTAG_TDO_PIN) ? 1 : 0);
#else
    return (0); // Not available
#endif
}

// nTRST Pin I/O -------------------------------------------

/** nTRST I/O pin: Get Input.
\return Current status of the nTRST DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_nTRST_IN(void)
{
    return (0); // Not available
}

/** nTRST I/O pin: Set Output.
\param bit JTAG TRST Test Reset pin status:
           - 0: issue a JTAG TRST Test Reset.
           - 1: release JTAG TRST Test Reset.
*/
__STATIC_FORCEINLINE void PIN_nTRST_OUT(uint32_t bit)
{
    ; // Not available
}

// nRESET Pin I/O------------------------------------------

/** nRESET I/O pin: Get Input.
\return Current status of the nRESET DAP hardware I/O pin.
*/
__STATIC_FORCEINLINE uint32_t PIN_nRESET_IN(void)
{
    return ((nRESET_PIN_PORT->IDR >> nRESET_PIN_Bit) & 1);
}

/** nRESET I/O pin: Set Output.
\param bit target device hardware reset pin status:
           - 0: issue a device hardware reset.
           - 1: release device hardware reset.
*/
// TODO - sw specific implementation should be created

__STATIC_FORCEINLINE void PIN_nRESET_OUT(uint32_t bit)
{
    if (bit & 1)
        nRESET_PIN_PORT->BSRR = nRESET_PIN;
    else
    {
        swd_write_word((uint32_t)&SCB->AIRCR, ((0x5FA << SCB_AIRCR_VECTKEY_Pos) | SCB_AIRCR_SYSRESETREQ_Msk));
        nRESET_PIN_PORT->BRR = nRESET_PIN;
    }
}

//**************************************************************************************************
/**
\defgroup DAP_Config_LEDs_gr CMSIS-DAP Hardware Status LEDs
\ingroup DAP_ConfigIO_gr
@{

CMSIS-DAP Hardware may provide LEDs that indicate the status of the CMSIS-DAP Debug Unit.

It is recommended to provide the following LEDs for status indication:
 - Connect LED: is active when the DAP hardware is connected to a debugger.
 - Running LED: is active when the debugger has put the target device into running state.
*/

/** Debug Unit: Set status of Connected LED.
\param bit status of the Connect LED.
           - 1: Connect LED ON: debugger is connected to CMSIS-DAP Debug Unit.
           - 0: Connect LED OFF: debugger is not connected to CMSIS-DAP Debug Unit.
*/
__STATIC_INLINE void LED_CONNECTED_OUT(uint32_t bit)
{
    if (bit & 1)
        CONNECTED_LED_PORT->BSRR = CONNECTED_LED_PIN; // LED on
    else
        CONNECTED_LED_PORT->BRR = CONNECTED_LED_PIN; // LED off
}

/** Debug Unit: Set status Target Running LED.
\param bit status of the Target Running LED.
           - 1: Target Running LED ON: program execution in target started.
           - 0: Target Running LED OFF: program execution in target stopped.
*/
__STATIC_INLINE void LED_RUNNING_OUT(uint32_t bit)
{
    ; // Not available
}

///@}

//**************************************************************************************************
/**
\defgroup DAP_Config_Timestamp_gr CMSIS-DAP Timestamp
\ingroup DAP_ConfigIO_gr
@{
Access function for Test Domain Timer.

The value of the Test Domain Timer in the Debug Unit is returned by the function \ref TIMESTAMP_GET. By
default, the DWT timer is used.  The frequency of this timer is configured with \ref TIMESTAMP_CLOCK.

*/

/** Get timestamp of Test Domain Timer.
\return Current timestamp value.
*/
__STATIC_INLINE uint32_t TIMESTAMP_GET(void)
{
    return (DWT->CYCCNT) / (CPU_CLOCK / TIMESTAMP_CLOCK);
}

///@}

//**************************************************************************************************
/**
\defgroup DAP_Config_Initialization_gr CMSIS-DAP Initialization
\ingroup DAP_ConfigIO_gr
@{

CMSIS-DAP Hardware I/O and LED Pins are initialized with the function \ref DAP_SETUP.
*/

/** Setup of the Debug Unit I/O pins and LEDs (called when Debug Unit is initialized).
This function performs the initialization of the CMSIS-DAP Hardware I/O Pins and the
Status LEDs. In detail the operation of Hardware I/O and LED pins are enabled and set:
 - I/O clock system enabled.
 - all I/O pins: input buffer enabled, output pins are set to HighZ mode.
 - for nTRST, nRESET a weak pull-up (if available) is enabled.
 - LED output pins are enabled and LEDs are turned off.
*/
__STATIC_INLINE void DAP_SETUP(void)
{
    /* Enable port clock */
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_GPIOD_CLK_ENABLE();
    /* Configure I/O pin SWCLK */
    pin_out_init(SWCLK_TCK_PIN_PORT, SWCLK_TCK_PIN_Bit);
    SWCLK_TCK_PIN_PORT->BSRR = SWCLK_TCK_PIN;

    pin_out_init(SWDIO_OUT_PIN_PORT, SWDIO_OUT_PIN_Bit);
    SWDIO_OUT_PIN_PORT->BSRR = SWDIO_OUT_PIN;

    pin_in_init(SWDIO_IN_PIN_PORT, SWDIO_IN_PIN_Bit, 1);

    pin_out_od_init(nRESET_PIN_PORT, nRESET_PIN_Bit);
    nRESET_PIN_PORT->BSRR = nRESET_PIN;

    pin_out_init(CONNECTED_LED_PORT, CONNECTED_LED_PIN_Bit);
    CONNECTED_LED_PORT->BRR = CONNECTED_LED_PIN;
}

/*使用自定义特定 I/O 引脚或命令序列重置目标设备。
该函数允许可选地实现特定于设备的重置序列。
当执行  DAP_ResetTarget 命令时会调用此函数，
例如，当某个设备需要一个对时间要求严格的解锁序列来启用调试端口时，就需要调用该函数。
返回值：
0 = 未实现特定于设备的重置序列。
1 = 已实现特定于设备的重置序列。*/

__STATIC_INLINE uint32_t RESET_TARGET(void)
{
    return (0); // change to '1' when a device reset sequence is implemented
}

///@}

#endif /* __DAP_CONFIG_H__ */
